home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / DB / NestedSet / TigraMenu.php < prev    next >
PHP Script  |  2004-03-24  |  12KB  |  403 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PEAR :: DB_NestedSet_TigraMenu                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Daniel Khan <dk@webcluster.at>                              |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: TigraMenu.php,v 1.6 2003/05/25 00:46:46 datenpunk Exp $
  20. //
  21.  
  22. // {{{ DB_NestedSet_TigraMenu:: class
  23.  
  24. /**
  25. * This class can be used to generate the data to build javascript popup menu
  26. * from a DB_NestedSet node array.
  27. * The Javascript part is done using the free available TigraMenu
  28. * available at http://www.softcomplex.com/products/tigra_menu/.
  29. * Currently version 1.0 is supported.
  30. * Parts of this class where taken ftom the TreemMenu driver by Jason Rust
  31. *
  32. * @author       Daniel Khan <dk@webcluster.at>
  33. * @package      DB_NestedSet
  34. * @version      $Revision: 1.6 $
  35. * @access       public
  36. */
  37. // }}}
  38. class DB_NestedSet_TigraMenu extends DB_NestedSet_Output {
  39.     // {{{{ properties
  40.     
  41.     /**
  42.     * @var integer The depth of the current menu.
  43.     * @access private
  44.     */
  45.     var $_levels    = 1;
  46.  
  47.     /**
  48.     * @var integer The level we started at
  49.     * @access private
  50.     */    
  51.     var $_levelOffset = false;
  52.     
  53.     
  54.     /**
  55.     * @var array The current menu structure
  56.     * @access private
  57.     */
  58.     var $_structTigraMenu = false;
  59.  
  60.     /**
  61.     * @var array The longest text for each level
  62.     * @access private
  63.     */    
  64.     var $_strlenByLevel    = array();
  65.  
  66.     // }}}
  67.     // {{{ DB_NestedSet_TigraMenu
  68.     
  69.     /**
  70.     * Constructor
  71.     *
  72.     * @param array $params A hash with parameters needed by the class
  73.     * @see _createFromStructure()
  74.     * @return bool
  75.     **/
  76.     function &DB_NestedSet_TigraMenu($params) {
  77.         $this->_menu_id = $params['menu_id'];
  78.         $this->_structTigraMenu = $this->_createFromStructure($params);
  79.         return true;
  80.     }
  81.     
  82.     // }}}
  83.     // {{{ _createFromStructure()
  84.     
  85.     /**
  86.     * Creates the JavaScript array for TigraMenu
  87.     * Initially this method was introduced for the TreeMenu driver by Jason Rust
  88.     *
  89.     * o 'structure' => the result from $nestedSet->getAllNodes(true)
  90.     * o 'textField' => the field in the table that has the text for node
  91.     * o 'linkField' => the field in the table that has the link for the node
  92.     *
  93.     * @access private
  94.     * @return string The TigraMenu JavaScript array
  95.     */
  96.     function &_createFromStructure($params)
  97.     {
  98.         // Basically we go through the array of nodes checking to see
  99.         // if each node has children and if so recursing.  The reason this
  100.         // works is because the data from getAllNodes() is ordered by level
  101.         // so a root node will always be first, and sub children will always
  102.         // be after them.
  103.         
  104.         static $rootlevel;
  105.         
  106.         // always start at level 1
  107.         if (!isset($params['currentLevel'])) {
  108.             $params['currentLevel'] = 1;
  109.         }
  110.         
  111.         if (!isset($rootlevel)) {
  112.             $rootlevel = $params['currentLevel'];
  113.         }
  114.         
  115.         if (isset($params['tigraMenu'])) {
  116.             $tigraMenu = $tigraMenu.$params['tigraMenu'];
  117.         }
  118.         
  119.         if(!$this->_levelOffset) {
  120.             $this->_levelOffset = $params['currentLevel'];
  121.         }
  122.  
  123.         if($this->_levels < ($params['currentLevel']- $this->_levelOffset)) {
  124.             $this->_levels = $params['currentLevel'] - $this->_levelOffset;
  125.         }
  126.         
  127.         
  128.         // have to use a while loop here because foreach works on a copy of the array and
  129.         // the child nodes are passed by reference during the recursion so that the parent
  130.         // will know when they have been hit.
  131.         reset($params['structure']);
  132.         while(list($key, $node) = each($params['structure'])) {
  133.             // see if we've already been here before
  134.             if (isset($node['hit']) || $node['level'] < $params['currentLevel']) {
  135.                 continue;
  136.             }
  137.             
  138.             // mark that we've hit this node
  139.             $params['structure'][$key]['hit'] = $node['hit'] = true;
  140.             
  141.             $tag = array(
  142.             isset($node[$params['textField']]) ? "'".$node[$params['textField']]."'" : 'null',
  143.             isset($node[$params['linkField']]) ? "'".$node[$params['linkField']]."'" : 'null'
  144.             );
  145.             
  146.             if (!$this->_strlenByLevel[$params['currentLevel'] - $this->_levelOffset] || 
  147.                 strlen($node[$params['textField']]) > $this->_strlenByLevel[$params['currentLevel'] - $this->_levelOffset]) {
  148.                 $this->_strlenByLevel[$params['currentLevel'] - $this->_levelOffset] = strlen($node[$params['textField']]);
  149.             };
  150.             
  151.             $tigraMenu = $tigraMenu.$this->_openSubMenu($tag);
  152.             
  153.             // see if it has children
  154.             if (($node['r'] - 1) != $node['l']) {
  155.                 $children = array();
  156.                 // harvest all the children
  157.                 $tempStructure = $params['structure'];
  158.                 foreach ($tempStructure as $childKey => $childNode) {
  159.                     if (!isset($childNode['hit']) &&
  160.                     $node['rootid'] == $childNode['rootid'] &&
  161.                     $node['l'] < $childNode['l'] &&
  162.                     $node['r'] > $childNode['r'] &&
  163.                     $childNode['level'] > $params['currentLevel']) {
  164.                         // important that we assign it by reference here, so that when the child
  165.                         // marks itself 'hit' the parent loops will know
  166.                         $children[] =& $params['structure'][$childKey];
  167.                     }
  168.                 }
  169.                 
  170.                 $recurseParams = $params;
  171.                 $recurseParams['structure'] = $children;
  172.                 $recurseParams['currentLevel']++;
  173.                 $tigraMenu = $tigraMenu.$this->_createFromStructure($recurseParams);
  174.             }
  175.             
  176.             $tigraMenu = $tigraMenu.$this->_closeSubMenu();
  177.         }
  178.         return $tigraMenu;
  179.     }
  180.     
  181.     // }}}
  182.     // {{{ _openMenu()
  183.     
  184.     /**
  185.     * Returns the string which opens the JavaScript menu
  186.     * 
  187.     * @access private
  188.     * @param int $menu_id ID of the menu needed to use more than one menu on a page
  189.     * @return string The JavaScript piece
  190.     */
  191.     function _openMenu($menu_id=1) 
  192.     {
  193.         $str = false;
  194.         $str = $str."var MENU_ITEMS".$menu_id." = new Array();\n";
  195.         $str = $str."MENU_ITEMS".$menu_id." = [\n";
  196.         return $str;
  197.     }
  198.  
  199.     // }}}
  200.     // {{{ _openSubMenu()    
  201.     
  202.     /**
  203.     * Returns the string which opens a submenu within the JavaScript menu
  204.     * 
  205.     * @access private
  206.     * @param array $tag Contains the content of the current item (name, link)
  207.     * @return string The JavaScript piece
  208.     */
  209.     function _openSubMenu($tag) 
  210.     {
  211.         $rtag = implode(', ', $tag);
  212.         return "\n[".$rtag.',';
  213.     }
  214.  
  215.     // }}}
  216.     // {{{ _closeMenu()    
  217.         
  218.     /**
  219.     * Closes the JavaScript array
  220.     * 
  221.     * @access private
  222.     * @return string The JavaScript piece
  223.     */    
  224.     function _closeMenu() 
  225.     {
  226.         
  227.         return '];';
  228.     }
  229.  
  230.     // }}}
  231.     // {{{ _closeSubMenu()    
  232.         
  233.     /**
  234.     * Closes the JavaScript array of a submenu
  235.     * 
  236.     * @access private
  237.     * @return string The JavaScript piece
  238.     */        
  239.     function _closeSubMenu() 
  240.     {
  241.         return "\n],";
  242.     }
  243.     
  244.     // }}}
  245.     // {{{ _addStyles()
  246.  
  247.     /**
  248.     * Creates the JavaScript code which sets the styles for each level
  249.     * 
  250.     * @access private
  251.     * @param int $menu_id ID of the menu needed to use more than one menu on a page
  252.     * @param array $rootStyles Array of style attributes for the top items
  253.     * @param array $childStyles Array of style attributes for the sub items
  254.     * @return string The JavaScript piece
  255.     */        
  256.     function _addStyles($menu_id, $rootStyles, $childStyles = false) 
  257.     {
  258.         if (!$childStyles) {
  259.             $childStyles = $rootStyles;
  260.         }
  261.         
  262.         $styles = array();
  263.         foreach ($rootStyles as $key => $val) {
  264.             foreach ($val as $skey => $sval) {
  265.                 $styles["'$key'"][$skey][] = "'$sval'";
  266.             }
  267.         }
  268.         
  269.         foreach ($childStyles as $key => $val) {
  270.             foreach ($val as $skey => $sval) {
  271.                 for ($i = 1; $i <= $this->_levels; $i++) {
  272.                     $styles["'$key'"][$skey][] = "'$sval'";
  273.                 }
  274.             }
  275.         }
  276.         
  277.         $menustyles = false;
  278.         $menustyles = $menustyles . 'var MENU_STYLES'.$menu_id." = new Array();\n";
  279.         foreach ($styles as $key => $val) {
  280.             $menustyles = $menustyles.'MENU_STYLES'.$menu_id."[$key] = [\n";
  281.             foreach ($val as $skey => $sval) {
  282.                 $menustyles = $menustyles . "'$skey', [".implode(', ', $sval)."],\n";
  283.             }
  284.             $menustyles = $menustyles."];\n";
  285.         }
  286.         
  287.         return $menustyles;
  288.     }
  289.  
  290.     // }}}    
  291.     // {{{ _addGeometry()
  292.  
  293.     /**
  294.     * Creates the JavaScript code which sets the position and geometry of the menu
  295.     * 
  296.     * @access private
  297.     * @param int $menu_id ID of the menu needed to use more than one menu on a page
  298.     * @param array $rootGeometry Array of geometry attributes for the top items
  299.     * @param array $childGeometry  Array of geometry attributes for the sub items
  300.     * @return string The JavaScript piece
  301.     */        
  302.     function _addGeometry($menu_id, $rootGeometry, $childGeometry = false) 
  303.     {
  304.         if (!$childGeometry) {
  305.             $childGeometry = $rootGeometry;
  306.         }
  307.         
  308.         $params = array();
  309.         $geometry = array();
  310.         foreach ($rootGeometry as $key => $val) {
  311.             $geometry["'$key'"][] = $val;
  312.             $incr = false;
  313.             if (strpos($val, ',') !== false) {
  314.                 list($start, $interval) = explode(',',$val);
  315.                 $incr = true;
  316.             }
  317.             
  318.             $ratio = false;
  319.             if ($key == 'width' && strpos($val, '*') !== false) {
  320.                 $ratio = trim(str_replace('*','', $val));
  321.             }
  322.             if ($incr) {
  323.                 $val = trim($interval);
  324.                 if ($key == 'left' && preg_match('/[+-]/', $interval)) {
  325.                     $val = $params[0]['width'] + trim($val);
  326.                 }
  327.             } elseif ($incr) {
  328.                 $val = trim($start);
  329.             } elseif ($ratio) {
  330.                 $val = $ratio * $this->_strlenByLevel[0];
  331.             }
  332.             $geometry["'$key'"][0] = $val;
  333.             $params[0][$key] = $val;
  334.         }
  335.         
  336.         foreach($childGeometry as $key => $val) {
  337.             $incr = false;
  338.             if (strpos($val, ',') !== false) {
  339.                 list($start, $interval) = explode(',', $val);
  340.                 $incr = true;
  341.             }
  342.             
  343.             $ratio = false;
  344.             if ($key == 'width' && strpos($val, '*') !== false) {
  345.                 $ratio = trim(str_replace('*', '', $val));
  346.             }
  347.             
  348.             for ($i = 1; $i <= $this->_levels; $i++) {
  349.                 if ($incr && isset($lastval[$key])) {
  350.                     $val = trim($interval);
  351.                     if($key == 'block_left' && preg_match('/[+-]/', $interval)) {
  352.                         $val = $params[$i - 1]['width'] + trim($val);
  353.                     }
  354.                 } elseif($incr) {
  355.                     $val = trim($start);
  356.                 } elseif ($ratio) {
  357.                     $val = $ratio * $this->_strlenByLevel[$i];
  358.                     if($val < $params[0]['width']) {
  359.                         $val =     $params[0]['width'];
  360.                     }
  361.                 }
  362.                 
  363.                 $lastval[$key] = $val;
  364.                 $geometry["'$key'"][] = $val;
  365.                 $params[$i][$key] = $val;
  366.             }
  367.             
  368.         }
  369.         
  370.         $pos = false;
  371.         $pos = $pos . 'var MENU_POS'.$menu_id." = new Array();\n";
  372.         foreach ($geometry as $key => $val) {
  373.             $pos = $pos . 'MENU_POS' . $menu_id . "[$key] = [" . implode(', ', $val) . "];\n";
  374.         }
  375.         
  376.         return $pos;
  377.     }
  378.  
  379.     // }}}    
  380.     // {{{ printTree()
  381.         
  382.     /**
  383.     * Print's the current tree using the output driver
  384.     *
  385.     * @access public
  386.     */
  387.     function printTree() 
  388.     {
  389.         if (!$options = $this->_getOptions('printTree')) {
  390.             return PEAR::raiseError("TigraMenu::printTree() needs options. See TigraMenu::setOptions()", NESEO_ERROR_NO_OPTIONS, PEAR_ERROR_TRIGGER, E_USER_ERROR);
  391.         }
  392.         
  393.         echo $this->_openMenu($options['menu_id']) . $this->_structTigraMenu  .$this->_closeMenu();
  394.         echo "\n\n";
  395.         echo $this->_addStyles($options['menu_id'], $options['rootStyles'], $options['childStyles']);
  396.         echo "\n\n";
  397.         echo $this->_addGeometry($options['menu_id'], $options['rootGeometry'], $options['childGeometry']);
  398.     }
  399.     
  400.     // }}}
  401. }
  402. ?>
  403.